﻿/*
 * 创建人：童陟嵩
 * 创建日期：2019/12/16 14:50:30
 * 功能：
 * 版权：© 2019 上海电科电机科技有限公司, 上海电机系统节能工程技术研究中心有限公司 
 */

using MOTS.Core.Defs;
using MOTS.Export.Abstract;
using MOTS.Export.Attributes;
using MOTS.Export.Defs;
using MOTS.Export.Office;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Reflection;
using System.Collections;

namespace MOTS.Export.Extends
{
    public static class ExportHelper
    {
        public static string Export(this object value, IFormatProvider provider)
        {
            if (value == null)
            {
                return string.Empty;
            }
            else if (value is JudgeInfo)
            {
                var judgeInfoFormatter = (ExportJudgeInfoFormatter)provider.GetFormat(typeof(ExportJudgeInfoFormatter));

                return judgeInfoFormatter.Format(null, value, provider);
            }
            else if (value is double)
            {
                var doubleVal = (double)value;
                return doubleVal.ToString(provider);
            }
            else if (value is int)
            {
                var intVal = (int)value;
                return intVal.ToString(provider);
            }
            else if (value is float)
            {
                var floatVal = (float)value;
                return floatVal.ToString(provider);
            }
            else if (value is long)
            {
                var longVal = (long)value;
                return longVal.ToString(provider);
            }
            else if (value is DateTime)
            {
                var dateVal = (DateTime)value;
                return dateVal.ToString(provider);
            }

            return value.ToString();
        }

        public static string[] Export(this object[] values, IFormatProvider provider)
        {
            if (values == null)
            {
                return null;
            }

            if (!values.Any())
            {
                return new string[0];
            }

            var output = new string[values.Length];

            for (int i = 0; i < values.Length; i++)
            {
                output[i] = values[i].Export(provider);
            }

            return output;
        }

        /// <summary>
        /// 输出图片
        /// </summary>
        /// <param name="contents"></param>
        /// <param name="sheetName"></param>
        /// <param name="picName">数据库中保存的图片名称</param>
        /// <param name="rowOffset">行偏移，基于0，默认为1</param>
        /// <param name="width">图片占用的横向格数</param>
        /// <param name="height">图片占用的纵向格数</param>
        /// <param name="existingPictureCount">当前表格已存在的图片个数</param>
        /// <returns>返回下一行行号</returns>
        public static int AddPicture(this List<ExcelReportContent> contents, string sheetName, string picName, int rowOffset, int colOffset, ref int existingPictureCount, int width = 4, int height = 10)
        {
            if (string.IsNullOrEmpty(picName))
            {
                return rowOffset + height;
            }

            var picFullPath = Path.Combine(PathDefs.PictureDirectoryFullPath, picName);

            if (!string.IsNullOrEmpty(picFullPath))
            {
                var startColIndex = colOffset;
                var endColString = ColNumToString(startColIndex + width - 1);
                var startRowIndex = rowOffset + 1;
                var picContent = new ExcelPictureReportContent(sheetName)
                {
                    StartRange = $"{ColNumToString(startColIndex)}{startRowIndex}",
                    EndRange = $"{endColString}{rowOffset + height}",
                    PictureFullPath = picFullPath,
                    ExistingPictureCount = existingPictureCount
                };
                existingPictureCount++;
                contents.Add(picContent);
            }

            return rowOffset + height;
        }

        public static int AddRecords(this List<ExcelReportContent> contents, string sheetName, int rowOffset, object records, ExportFormatInfo formatInfo, ExportRecordsAttribute exportInfo)
        {
            var recordType = exportInfo.RecordType;
            var recordConstructor = recordType.GetConstructor(Type.EmptyTypes);
            var record = recordConstructor.Invoke(null) as IExportableRecord;

            if (record == null)
            {
                throw new ArgumentException($"{recordType}输出记录必须继承自IExportableRecord");
            }

            var titles = record.GetTitles();

            var startCol = exportInfo.ColumnOffset;
            var endCol = startCol + titles.Length;

            var content = new ExcelRangeReportContent(sheetName, $"{ColNumToString(startCol)}{rowOffset}", $"{ColNumToString(endCol)}{exportInfo.MaxCount + rowOffset}");

            content.AddOneRow(0, 0, titles);

            var exportableRecords = (records as IList)?.Cast<IExportableRecord>();

            if (exportableRecords == null)
            {
                throw new ArgumentException("输出记录转换失败，无法转换为IEumerable<IExportableRecord>");
            }

            var nextRow = 1;

            foreach (var rec in exportableRecords)
            {
                content.AddOneRow(nextRow, 0, formatInfo, rec.GetVaules());
                nextRow++;
            }

            contents.Add(content);

            return rowOffset + 1 + exportInfo.MaxCount;
        }

        /// <summary>
        /// 列索引字符形式转换为数字形式，A对应0
        /// </summary>
        /// <param name="colString">字符索引，以A起始</param>
        /// <returns></returns>
        private static int ColStringToNum(string colString)
        {
            if (!Regex.IsMatch(colString.ToUpper(), @"[A-Z]+"))
            {
                throw new Exception("列名不在范围");
            }

            int index = 0;
            char[] chars = colString.ToUpper().ToCharArray();
            for (int i = 0; i < chars.Length; i++)
            {
                index += (chars[i] - 'A' + 1) * (int)Math.Pow(26, chars.Length - i - 1);
            }
            return index - 1;
        }

        /// <summary>
        /// 列索引数字形式转换为字符形式，A对应0
        /// </summary>
        /// <param name="num">数字索引，以0起始</param>
        /// <returns></returns>
        private static string ColNumToString(int num)
        {
            if (num < 0)
            {
                throw new Exception("Index不在范围");
            }

            List<string> chars = new List<string>();
            do
            {
                if (chars.Count > 0)
                    num--;
                chars.Insert(0, ((char)(num % 26 + 'A')).ToString());
                num = ((num - num % 26) / 26);
            } while (num > 0);

            return string.Join(string.Empty, chars.ToArray());
        }
    }
}
